﻿using System;
using System.IO;
using System.Threading;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using AddIn.EA.Core.Common;
using AddIn.EA.Architecture.ComponentLogic;
using AddIn.EA.Framework;
using AddIn.EA.Framework.Common;

namespace AddIn.EA.Architecture.Presentation
{
    [AddInMenu("Add UX Components")]
    public partial class BuildViewSmartClient : BaseAddInArchitecture
    {

        #region [[ Atributos ]]

        public const string EASourcePath = @"C:\DSEPROJ\SINACOR\Tools\Dev\CDSC\AddInArchitecture\AddIn\AddIn.EA.Architecture.ExternalResources\Resources\ComponentesVisuaisInfra.eap";
        EA.Framework.RepositoryManager manager;
        BackgroundWorker bgwLod = new BackgroundWorker();

        #endregion


        #region [[ Construtores ]]

        public BuildViewSmartClient()
        {

            InitializeComponent();
            base.LoadAddInControls += new EventHandler(BuildProcessStructure_LoadAddInControls);
            this.bgwLod.DoWork += new DoWorkEventHandler(bgwLod_DoWork);
            this.bgwLod.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgwLod_RunWorkerCompleted);

        }

        #endregion


        #region [[ Eventos ]]

        /// <summary>
        /// Ao carregar Addin
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BuildProcessStructure_LoadAddInControls(object sender, EventArgs e)
        {
            this.bgwLod.RunWorkerAsync();
        }

        /// <summary>
        /// Conexão com o EA Source e carga assincrona da TreeView
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bgwLod_DoWork(object sender, DoWorkEventArgs e)
        {
            if (this.manager == null)
            {
                if (File.Exists(EASourcePath))
                {
                    this.manager = EA.Framework.RepositoryManager.OpenRepository(EASourcePath);

                    Package packageView = this.manager.GetPackageByName("SmartClient");
                    if (packageView == null)
                        MessageBox.Show("Não encontrada lista de componentes no source: " + EASourcePath, "Aviso", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
                    else
                        this.AddNode(packageView, this.trvInfraCompoments.Nodes[0]);
                }
                else
                    MessageBox.Show("Baixe o source de componentes no TFS para o caminho: " + EASourcePath, "Aviso", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            }
        }

        /// <summary>
        /// Ao comcluir processo assincrono, exibir treeview
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void bgwLod_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            this.trvInfraCompoments.Visible = true;
            this.trvNewElement.Visible = true;
            this.btnOk.Visible = true;
            this.btnAdd.Visible = true;
            this.btnRemove.Visible = true;
            this.lblAguarde.Visible = false;
        }

        /// <summary>
        /// Criar no EA a estrutura contida em trvNewElement
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnOk_Click(object sender, EventArgs e)
        {
            this.UpdateEA(base.Repository);
            this.Hide();
        }
        
        /// <summary>
        /// Adicionando componentes a nova View
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnAdd_Click(object sender, EventArgs e)
        {
            if (this.trvInfraCompoments.SelectedNode == null || this.trvInfraCompoments.SelectedNode.Tag == null || (this.trvInfraCompoments.SelectedNode.Tag is Package) )
                MessageBox.Show("Selecione um item de Componentes Disponives!", "Aviso", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            else
            {
                if (this.trvNewElement.SelectedNode == null)
                    this.trvNewElement.SelectedNode = this.trvNewElement.Nodes[0];
                
                this.trvNewElement.SelectedNode.Nodes.Add( (TreeNode) this.trvInfraCompoments.SelectedNode.Clone() );
                this.trvNewElement.SelectedNode.Expand();
            }
        }
        
        /// <summary>
        /// Removendo nodes da nova view
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnRemove_Click(object sender, EventArgs e)
        {
            if (this.trvNewElement.SelectedNode == null || (this.trvNewElement.SelectedNode == this.trvNewElement.Nodes[0]) )
                MessageBox.Show("Selecione um item da Nova View!", "Aviso", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);
            else
                this.trvNewElement.Nodes.Remove(this.trvNewElement.SelectedNode);
        }

        #endregion


        #region [[ Metodos ]]

        /// <summary>
        /// Adiciona package ao TreeView
        /// </summary>
        /// <param name="Package"></param>
        /// <param name="TvwNode"></param>
        private void AddNode(Package Package, TreeNode TvwNode)
        {

            TreeNode NewPackageNode = TvwNode.Nodes.Add(Package.ID.ToString(), Package.Name, 0, 0);
            NewPackageNode.Tag = Package;

            PackageList packgeList = Package.Packages;

            if (packgeList != null && packgeList.Count > 0)
            {
                foreach (Package packgeItem in packgeList)
                {
                    this.AddNode(packgeItem, NewPackageNode);
                }
            }

            if (Package.Elements != null && Package.Elements.Count > 0)
                this.AddNode(Package.Elements, NewPackageNode);    
        }

        /// <summary>
        /// Adiciona elementos ao TreeView
        /// </summary>
        /// <param name="ElementList"></param>
        /// <param name="TvwNode"></param>
        private void AddNode(ElementList ElementList, TreeNode TvwNode)
        {
            foreach (Element elementItem in ElementList)
            {                
                TreeNode NewNode = TvwNode.Nodes.Add(elementItem.ID.ToString(), elementItem.Name, 1, 1);
                NewNode.Tag = elementItem;
            }
        }

        /// <summary>
        /// Cria estrutura de elementos dentro da Package
        /// </summary>
        /// <param name="Node"></param>
        /// <param name="SelectedPackage"></param>
        /// <returns></returns>
        private void CreateElementInEA(TreeNode Node, Package SelectedPackage)
        {                        
            foreach (TreeNode nodeItem in Node.Nodes)
            {
                Element newElement = SelectedPackage.Elements.AddNew( ((Element) nodeItem.Tag).Name, ElementType.Class); //cria novo elemento associado a package
                this.CreateElementInEA(nodeItem, newElement, (Element) nodeItem.Tag);
            }
        }


        /// <summary>
        /// Cria estrutura dos elementos e sub elementos
        /// </summary>
        /// <param name="NewElement"></param>
        /// <param name="ElementToCopy"></param>
        private void CreateElementInEA(TreeNode Node, Element NewElement, Element ElementToCopy)
        {
            //Atributos do Elementos:           
            NewElement.Notes = ElementToCopy.Notes;
            NewElement.Stereotype = ElementToCopy.Stereotype;

            //Propriedades do Elemento:
            foreach (AttributeClass itemAtribute in ElementToCopy.Attributes)
            {
               AttributeClass newAtribute = NewElement.Attributes.AddNew(itemAtribute.Name, itemAtribute.Type);
               newAtribute.Scope = itemAtribute.Scope;
               newAtribute.Stereotype = itemAtribute.Stereotype;
               newAtribute.Notes = itemAtribute.Notes;
               newAtribute.Update();
            }

            //Metodos do Elemento:
            foreach (AddIn.EA.Framework.Method itemMethod in ElementToCopy.Methods)
            {
                AddIn.EA.Framework.Method newMethod = NewElement.Methods.AddNew(itemMethod.Name, itemMethod.ReturnType);
                newMethod.Scope = itemMethod.Scope;
                newMethod.IsStatic = itemMethod.IsStatic;
                newMethod.Notes = itemMethod.Notes;
                newMethod.Behavior = itemMethod.Behavior;
                newMethod.Stereotype = itemMethod.Stereotype;
                newMethod.Update();
            }

            NewElement.Refresh();

            if (Node.Nodes.Count > 0)
            {
                foreach (TreeNode itemNode in Node.Nodes)
                {
                    Element newChield = NewElement.Elements.AddNew(((Element) itemNode.Tag).Name, ElementType.Class); //cria novo elemento associado ao elemento
                    this.CreateElementInEA(itemNode, newChield, (Element) itemNode.Tag);        
                }
            }

            NewElement.Refresh();
        }


        /// <summary>
        /// Override da atualização da classe base
        /// </summary>
        /// <param name="repository"></param>
        /// <returns></returns>
        protected override bool UpdateEA(RepositoryManager repository)
        {
            if (this.trvNewElement.Nodes[0].Nodes.Count == 0)
                MessageBox.Show("Não existem itens para criar a View!", "Aviso", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

            else if (this.manager.GetSelectedObject().GetType() != typeof(Package) )
                MessageBox.Show("Selecione uma Packge!", "Aviso", MessageBoxButtons.OK, MessageBoxIcon.Exclamation);

            else
                this.CreateElementInEA(this.trvNewElement.Nodes[0], (Package) base.Repository.GetSelectedObject());

            return false;
        }

        protected override bool CheckShowForm(IElement selectedElement, MenuLocation location)
        {
            return (selectedElement is Package);
        }

        #endregion




    }

}